.globl read_matrix

.text
# ==============================================================================
# FUNCTION: Allocates memory and reads in a binary file as a matrix of integers
#
# FILE FORMAT:
#   The first 8 bytes are two 4 byte ints representing the # of rows and columns
#   in the matrix. Every 4 bytes afterwards is an element of the matrix in
#   row-major order.
# Arguments:
#   a0 (char*) is the pointer to string representing the filename
#   a1 (int*)  is a pointer to an integer, we will set it to the number of rows
#   a2 (int*)  is a pointer to an integer, we will set it to the number of columns
# Returns:
#   a0 (int*)  is the pointer to the matrix in memory
# Exceptions:
#   - If malloc returns an error,
#     this function terminates the program with error code 26
#   - If you receive an fopen error or eof,
#     this function terminates the program with error code 27
#   - If you receive an fclose error or eof,
#     this function terminates the program with error code 28
#   - If you receive an fread error or eof,
#     this function terminates the program with error code 29
# ==============================================================================
read_matrix:
	# Prologue
    addi sp, sp, -20
    sw ra, 0(sp)
    sw s1, 4(sp)
    sw s2, 8(sp)
    sw s3, 12(sp)
    sw s4, 16(sp)
    addi sp, sp, -8
    sw a1, 0(sp)
    sw a2, 4(sp)
    li a1, 0 # read only
    jal ra, fopen
    li t0, -1
    beq a0, t0, fopen_error 
    mv s1, a0     # file descriptor
    li t1, 8
    lw a1, 0(sp)
    lw a2, 4(sp)
    addi sp, sp, 8
    
    # call malloc
    addi sp, sp, -8
    sw a1, 0(sp)
    sw a2, 4(sp)
    li a0, 8
    jal ra, malloc
    beq a0, x0, malloc_error
    lw a1, 0(sp)
    lw a2, 4(sp)
    addi sp, sp, 8
    
    # fread rows cols
    addi sp, sp, -16
    sw a1, 0(sp)
    sw a2, 4(sp)
    sw t0, 8(sp)
    sw t1, 12(sp)
    mv a1, a0 # pointer to buffer
    mv s2, a1
    mv a0, s1 # file descriptor
    li a2, 8  # The number of bytes to read from the file
    jal ra, fread
    lw t1, 12(sp)
    bne a0, t1, fread_error
    lw a1, 0(sp)
    lw a2, 4(sp)
    lw t0, 8(sp)
    addi sp, sp, 16
     
    lw s3, 0(s2) # rows
    lw s4, 4(s2) # cols
    
    sw s3, 0(a1)
    sw s4, 0(a2)
    
    # call malloc save matrix
    addi sp, sp, -16
    sw a1, 0(sp)
    sw a2, 4(sp)
    sw t0, 8(sp)
    sw t1, 12(sp)
    mul a0, s3, s4
    slli a0, a0, 2
    mv s2, a0 # number of bytes to malloc
    jal ra, malloc
    beq a0, x0, malloc_error
    lw a1, 0(sp)
    lw a2, 4(sp)
    lw t0, 8(sp)
    lw t1, 12(sp)
    addi sp, sp, 16
    
    # call fread
    addi sp, sp, -16
    sw a1, 0(sp)
    sw a2, 4(sp)
    sw t0, 8(sp)
    sw t1, 12(sp)
    mv a1, a0 # void*
    mv s3, a1 
    mv a0, s1 # file descriptor
    jal ra, fread
    bne a0, s2, fread_error
    lw a1, 0(sp)
    lw a2, 4(sp)
    lw t0, 8(sp)
    lw t1, 12(sp)
    addi sp, sp, 16


    # fclose
#     addi sp, sp, -4
#     sw a0, 0(sp)
    mv a0, s1
    jal ra, fclose
    li t0, -1
    beq a0, t0, fclose_error
#     lw a0, 0(sp)
#     addi sp, sp, 4
    mv a0, s3
    
	# Epilogue
    lw ra, 0(sp)
    lw s1, 4(sp)
    lw s2, 8(sp)
    lw s3, 12(sp)
    lw s4, 16(sp)
    addi sp, sp, 20
	ret
fopen_error:
    li a0, 27
    j exit
malloc_error:
    li a0, 26
    j exit
fclose_error:
    li a0, 28
    j exit
fread_error:
    li a0, 29
    j exit